/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007 - 2008 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.form.editor.model.form.factory;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;

import com.genia.toolbox.basics.editor.model.document.VariableModel;
import com.genia.toolbox.form.editor.FormEditorApplication;
import com.genia.toolbox.form.editor.model.form.impl.ContainerFormModel;
import com.genia.toolbox.form.editor.model.form.impl.FormModel;
import com.genia.toolbox.form.editor.model.form.impl.FormType;
import com.genia.toolbox.web.gwt.basics.client.i18n.GwtI18nMessage;
import com.genia.toolbox.web.gwt.form.client.form.EnumDescriptableValuedItemEntryList;
import com.genia.toolbox.web.gwt.form.client.form.Form;
import com.genia.toolbox.web.gwt.form.client.form.HorizontalForm;
import com.genia.toolbox.web.gwt.form.client.form.LabeledForm;
import com.genia.toolbox.web.gwt.form.client.form.SimpleValuedItemEntryList;
import com.genia.toolbox.web.gwt.form.client.form.TabForm;
import com.genia.toolbox.web.gwt.form.client.form.ValuedItemEntry;
import com.genia.toolbox.web.gwt.form.client.form.VerticalForm;
import com.genia.toolbox.web.gwt.form.client.form.impl.AbstractItem;
import com.genia.toolbox.web.gwt.form.client.form.impl.AbstractSimpleItem;
import com.genia.toolbox.web.gwt.form.client.form.impl.AbstractValuedItem;
import com.genia.toolbox.web.gwt.form.client.form.impl.EnumDescriptableValuedItemEntryListImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.HorizontalFormImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.LabeledFormImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.SimpleValuedItemEntryListImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.TabFormImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.ValuedItemEntryImpl;
import com.genia.toolbox.web.gwt.form.client.form.impl.VerticalFormImpl;
import com.genia.toolbox.web.gwt.form.client.validator.Validator;
import com.genia.toolbox.web.gwt.form.server.description.item.ItemDescription;
import com.genia.toolbox.web.gwt.form.server.description.validator.ValidatorDescription;
import com.genia.toolbox.web.portlet.description.VariableDescription;
import com.genia.toolbox.web.portlet.description.ContainerPortletDescription.LayoutDirection;
import com.genia.toolbox.web.portlet.description.impl.BooleanVariableDescription;
import com.genia.toolbox.web.portlet.description.impl.LongVariableDescription;

/**
 * The model factory.
 */
public class FormFactory
{

  /**
   * The form editor application.
   */
  private FormEditorApplication formEditorApplication;



  /**
   * Constructor.
   * 
   * @param formEditorApplication
   *          The form editor application.
   */
  public FormFactory(FormEditorApplication formEditorApplication)
  {
    super();
    this.formEditorApplication = formEditorApplication;
  }



  /**
   * Create the root form based on its type.
   * 
   * @param type
   *          the root form type.
   * @param name
   *          the root form name.
   * @param tabType
   *          the root form tab type.
   * @return the root form.
   */
  public FormModel createRootForm(String name, FormType type, FormType tabType)
  {
    ContainerFormModel form = (ContainerFormModel) this.createRootForm(name, type);
    if (form == null) {
      if (type != null) {
        form = new ContainerFormModel();
        form.setType(type);
        form.setName(name);
        form.setElementName(name);
        form.setMinNbSubForms(1);
        form.setMaxNbSubForms(Integer.MAX_VALUE);
        form.setDirection(null);

        ContainerFormModel labeledFormModel = (ContainerFormModel) this.createRootForm("", FormType.LABELED);
        labeledFormModel.setSubElement(true);
        labeledFormModel.setParentID(form.getUniqueID());
        labeledFormModel.setDocumentID(form.getDocumentID());
        labeledFormModel.setParentDirection(form.getDirection());

        ContainerFormModel subFormModel = (ContainerFormModel) this.createRootForm(name, tabType);
        subFormModel.setSubElement(true);
        subFormModel.setParentID(labeledFormModel.getUniqueID());
        subFormModel.setDocumentID(labeledFormModel.getDocumentID());
        subFormModel.setParentDirection(labeledFormModel.getDirection());
        List<FormModel> subforms = new ArrayList<FormModel>();
        subforms.add(subFormModel);
        labeledFormModel.setSubforms(subforms);

        List<FormModel> sublabeledforms = new ArrayList<FormModel>();
        sublabeledforms.add(labeledFormModel);
        form.setSubforms(sublabeledforms);
      }
      else {
        form = new ContainerFormModel();
        form.setSubElement(true);
        form.setType(FormType.LABELED);
        form.setName(name);
        form.setElementName(name);
        form.setMinNbSubForms(1);
        form.setMaxNbSubForms(1);
        form.setDirection(null);

        ContainerFormModel subform = new ContainerFormModel();
        subform.setSubElement(true);
        subform.setType(tabType);
        subform.setName(name);
        subform.setElementName(name);
        subform.setMinNbSubForms(1);
        subform.setMaxNbSubForms(Integer.MAX_VALUE);
        if (FormType.HORIZONTAL.equals(tabType)) {
          subform.setDirection(LayoutDirection.HORIZONTAL);
        }
        else {
          subform.setDirection(LayoutDirection.VERTICAL);
        }

        List<FormModel> subforms = new ArrayList<FormModel>();
        subforms.add(subform);
        form.setSubforms(subforms);
      }
    }
    else {
      // There should not be a root form with a null type.
    }
    return form;
  }



  /**
   * Create the root form based on its type.
   * 
   * @param type
   *          the root form type.
   * @param name
   *          the root form name.
   * @return the root form.
   */
  private FormModel createRootForm(String name, FormType type)
  {
    ContainerFormModel form = null;
    if (FormType.HORIZONTAL.equals(type)) {
      form = new ContainerFormModel();
      form.setType(type);
      form.setName(name);
      form.setElementName(name);
      form.setMinNbSubForms(1);
      form.setMaxNbSubForms(Integer.MAX_VALUE);
      form.setDirection(LayoutDirection.HORIZONTAL);
    }
    else if (FormType.VERTICAL.equals(type)) {
      form = new ContainerFormModel();
      form.setType(type);
      form.setName(name);
      form.setElementName(name);
      form.setMinNbSubForms(1);
      form.setMaxNbSubForms(Integer.MAX_VALUE);
      form.setDirection(LayoutDirection.VERTICAL);
    }
    else if (FormType.LABELED.equals(type)) {
      form = new ContainerFormModel();
      form.setType(type);
      form.setName(name);
      form.setElementName(name);
      form.setMinNbSubForms(1);
      form.setMaxNbSubForms(1);
      form.setDirection(null);
    }
    else {
      // There should not be a root form with a null type.
    }
    return form;
  }



  /**
   * Convert a form to its model.
   * 
   * @param form
   *          the form.
   * @return the form model.
   */
  public FormModel convert(Form form)
  {
    FormModel formModel = null;
    if (form instanceof HorizontalForm) {
      HorizontalFormImpl horizontalForm = (HorizontalFormImpl) form;
      ContainerFormModel horizontalFormModel = new ContainerFormModel();
      horizontalFormModel.setDescription(null);
      horizontalFormModel.setName(horizontalForm.getName());
      horizontalFormModel.setDescriptionName(form.getClass().getCanonicalName());
      horizontalFormModel.setDirection(LayoutDirection.HORIZONTAL);
      horizontalFormModel.setElementName(FormType.HORIZONTAL.name());
      horizontalFormModel.setEntries(null);
      horizontalFormModel.setEnumEntry(null);
      horizontalFormModel.setHasEntries(false);
      horizontalFormModel.setLabelKey(null);
      horizontalFormModel.setMaxNbSubForms(Integer.MAX_VALUE);
      horizontalFormModel.setMinNbSubForms(0);
      horizontalFormModel.setParameters(null);

      horizontalFormModel.setValidatorClassName(null);
      horizontalFormModel.setValidatorDescriptionName(null);
      horizontalFormModel.setValidatorParameters(null);

      horizontalFormModel.setType(FormType.HORIZONTAL);
      List<FormModel> subforms = new ArrayList<FormModel>();
      FormModel subFormModel = null;
      Form subform = null;
      for (Object object : horizontalForm.getForms()) {
        if (object instanceof Form) {
          subform = (Form) object;
          subFormModel = this.convert(subform);
          subFormModel.setSubElement(true);
          subFormModel.setParentID(horizontalFormModel.getUniqueID());
          subFormModel.setDocumentID(horizontalFormModel.getDocumentID());
          subFormModel.setParentDirection(horizontalFormModel.getDirection());
          subforms.add(subFormModel);
        }
      }
      horizontalFormModel.setSubforms(subforms);
      formModel = horizontalFormModel;
    }
    else if (form instanceof VerticalForm) {
      VerticalFormImpl verticalForm = (VerticalFormImpl) form;
      ContainerFormModel verticalFormModel = new ContainerFormModel();
      verticalFormModel.setDescription(null);
      verticalFormModel.setName(verticalForm.getName());
      verticalFormModel.setDescriptionName(form.getClass().getCanonicalName());
      verticalFormModel.setDirection(LayoutDirection.VERTICAL);
      verticalFormModel.setElementName(FormType.VERTICAL.name());
      verticalFormModel.setEntries(null);
      verticalFormModel.setEnumEntry(null);
      verticalFormModel.setHasEntries(false);
      verticalFormModel.setLabelKey(null);
      verticalFormModel.setMaxNbSubForms(Integer.MAX_VALUE);
      verticalFormModel.setMinNbSubForms(0);
      verticalFormModel.setParameters(null);

      verticalFormModel.setValidatorClassName(null);
      verticalFormModel.setValidatorDescriptionName(null);
      verticalFormModel.setValidatorParameters(null);

      verticalFormModel.setType(FormType.VERTICAL);
      List<FormModel> subforms = new ArrayList<FormModel>();
      FormModel subFormModel = null;
      Form subform = null;
      for (Object object : verticalForm.getForms()) {
        if (object instanceof Form) {
          subform = (Form) object;
          subFormModel = this.convert(subform);
          subFormModel.setSubElement(true);
          subFormModel.setParentID(verticalFormModel.getUniqueID());
          subFormModel.setDocumentID(verticalFormModel.getDocumentID());
          subFormModel.setParentDirection(verticalFormModel.getDirection());
          subforms.add(subFormModel);
        }
      }
      verticalFormModel.setSubforms(subforms);
      formModel = verticalFormModel;
    }
    else if (form instanceof TabForm) {
      TabForm tabForm = (TabForm) form;

      ContainerFormModel tabFormModel = new ContainerFormModel();
      tabFormModel.setDescription(null);
      tabFormModel.setName(tabForm.getName());
      tabFormModel.setDescriptionName(form.getClass().getCanonicalName());
      tabFormModel.setDirection(LayoutDirection.VERTICAL);
      tabFormModel.setElementName(FormType.VERTICAL.name());
      tabFormModel.setEntries(null);
      tabFormModel.setEnumEntry(null);
      tabFormModel.setHasEntries(false);
      tabFormModel.setLabelKey(null);
      tabFormModel.setMaxNbSubForms(Integer.MAX_VALUE);
      tabFormModel.setMinNbSubForms(0);
      tabFormModel.setParameters(null);
      tabFormModel.setValidatorClassName(null);
      tabFormModel.setValidatorDescriptionName(null);
      tabFormModel.setValidatorParameters(null);
      tabFormModel.setType(FormType.TAB);

      List<FormModel> subforms = new ArrayList<FormModel>();
      FormModel subFormModel = null;
      Form subform = null;
      for (Object object : tabForm.getForms()) {
        if (object instanceof Form) {
          subform = (Form) object;
          subFormModel = this.convert(subform);
          subFormModel.setSubElement(true);
          subFormModel.setParentID(tabFormModel.getUniqueID());
          subFormModel.setDocumentID(tabFormModel.getDocumentID());
          subFormModel.setParentDirection(tabFormModel.getDirection());
          subforms.add(subFormModel);
        }
      }
      tabFormModel.setSubforms(subforms);
      formModel = tabFormModel;
    }
    else if (form instanceof LabeledForm) {
      LabeledForm labeledForm = (LabeledForm) form;

      ContainerFormModel labeledFormModel = new ContainerFormModel();
      labeledFormModel.setDescription(null);
      labeledFormModel.setName(labeledForm.getName());
      labeledFormModel.setDescriptionName(form.getClass().getCanonicalName());
      labeledFormModel.setDirection(null);
      labeledFormModel.setElementName(null);
      labeledFormModel.setEntries(null);
      labeledFormModel.setEnumEntry(null);
      labeledFormModel.setHasEntries(false);
      labeledFormModel.setLabelKey(labeledForm.getLabel().getKey());
      labeledFormModel.setMaxNbSubForms(1);
      labeledFormModel.setMinNbSubForms(1);
      labeledFormModel.setParameters(null);

      labeledFormModel.setValidatorClassName(null);
      labeledFormModel.setValidatorDescriptionName(null);
      labeledFormModel.setValidatorParameters(null);

      labeledFormModel.setType(FormType.LABELED);
      List<FormModel> subforms = new ArrayList<FormModel>();
      FormModel subFormModel = null;
      Form subform = labeledForm.getSubForm();
      if (subform != null) {
        subFormModel = this.convert(subform);
        subFormModel.setSubElement(true);
        subFormModel.setParentID(labeledFormModel.getUniqueID());
        subFormModel.setDocumentID(labeledFormModel.getDocumentID());
        subFormModel.setParentDirection(labeledFormModel.getDirection());
        subforms.add(subFormModel);
      }
      labeledFormModel.setSubforms(subforms);
      formModel = labeledFormModel;
    }
    else if (form instanceof AbstractItem) {
      AbstractItem item = (AbstractItem) form;
      ItemDescription itemDescription = this.formEditorApplication.getItemFormDescription(form.getClass().getCanonicalName());
      FormModel itemFormModel = new FormModel();
      itemFormModel.setDescription(itemDescription.getDescription());
      itemFormModel.setDescriptionName(form.getClass().getCanonicalName());
      itemFormModel.setElementName(this.formEditorApplication.getTranslation(itemDescription.getName()));
      itemFormModel.setHasEntries(itemDescription.hasEntries());
      if (itemDescription.hasEntries()) {
        List<VariableModel> itemEntries = new ArrayList<VariableModel>();
        AbstractValuedItem valuedItem = (AbstractValuedItem) form;
        if (valuedItem.getEntries() instanceof SimpleValuedItemEntryList) {
          SimpleValuedItemEntryList entries = (SimpleValuedItemEntryList) valuedItem.getEntries();
          ValuedItemEntry entry = null;
          VariableModel variable = null;
          if (entries != null && entries.getValuedItemEntries() != null) {
            for (Object object : entries.getValuedItemEntries()) {
              if (object instanceof ValuedItemEntry) {
                entry = (ValuedItemEntry) object;
                variable = new VariableModel(entry.getLabel().getKey(), entry.getValue());
                variable.setMandatory(true);
                itemEntries.add(variable);
              }
            }
          }
          itemFormModel.setEntries(itemEntries);
          itemFormModel.setEnumEntry(null);
        }
        else {
          EnumDescriptableValuedItemEntryList entries = (EnumDescriptableValuedItemEntryList) valuedItem.getEntries();
          itemFormModel.setEnumEntry(entries.getEnumClassName());
          itemFormModel.setEntries(null);
        }
      }
      else {
        itemFormModel.setEntries(null);
        itemFormModel.setEnumEntry(null);
      }
      itemFormModel.setLabelKey(item.getLabelKey().getKey());
      itemFormModel.setName(item.getName());
      List<VariableModel> parameters = new LinkedList<VariableModel>();
      String value = null;
      for (VariableDescription variableDescription : itemDescription.getVariableDescriptions()) {
        boolean isLongValue = false;
        boolean isBooleanValue = false;
        if (variableDescription instanceof LongVariableDescription) {
          isLongValue = true;
        }
        else if (variableDescription instanceof BooleanVariableDescription) {
          isBooleanValue = true;
        }
        value = this.getProperty(form, variableDescription.getName()).toString();
        VariableModel variableModel = new VariableModel(variableDescription.getName(), variableDescription.getDescription(), value, variableDescription.getValues(), variableDescription.isMandatory(),
            isLongValue, isBooleanValue);
        parameters.add(variableModel);
      }
      itemFormModel.setParameters(parameters);
      itemFormModel.setType(null);

      if (item instanceof AbstractSimpleItem) {
        AbstractSimpleItem simpleItem = (AbstractSimpleItem) item;
        itemFormModel.setCanHaveValidator(true);
        if (simpleItem.getValidator() != null) {
          Validator validator = simpleItem.getValidator();
          ValidatorDescription validatorDescription = this.formEditorApplication.getValidatorDescription(validator.getClass().getCanonicalName());
          itemFormModel.setValidatorClassName(validatorDescription.getClassName());
          itemFormModel.setValidatorDescriptionName(validatorDescription.getDescription().getKey());
          List<VariableModel> validatorParameters = new ArrayList<VariableModel>();
          for (VariableDescription variableDescription : validatorDescription.getVariableDescriptions()) {
            boolean isLongValue = false;
            boolean isBooleanValue = false;
            if (variableDescription instanceof LongVariableDescription) {
              isLongValue = true;
            }
            else if (variableDescription instanceof BooleanVariableDescription) {
              isBooleanValue = true;
            }
            value = this.getProperty(validator, variableDescription.getName()).toString();
            VariableModel variableModel = new VariableModel(variableDescription.getName(), variableDescription.getDescription(), value, variableDescription.getValues(), variableDescription
                .isMandatory(), isLongValue, isBooleanValue);
            validatorParameters.add(variableModel);
          }
          itemFormModel.setValidatorParameters(validatorParameters);
        }
      }
      formModel = itemFormModel;
    }
    return formModel;
  }



  /**
   * Convert a form model to a form.
   * 
   * @param formModel
   *          the form model.
   * @return the form.
   */
  @SuppressWarnings("unchecked")
  public Form convert(FormModel formModel)
  {
    Form form = null;
    FormType formType = formModel.getType();
    if (FormType.HORIZONTAL.equals(formType)) {
      ContainerFormModel containerModel = (ContainerFormModel) formModel;
      HorizontalFormImpl horizontalForm = new HorizontalFormImpl();
      horizontalForm.setName(containerModel.getName());
      List<Form> subforms = horizontalForm.getForms();
      for (FormModel subformModel : containerModel.getSubElements()) {
        subforms.add(this.convert(subformModel));
      }
      horizontalForm.setForms(subforms);
      form = horizontalForm;
    }
    else if (FormType.VERTICAL.equals(formType)) {
      ContainerFormModel containerModel = (ContainerFormModel) formModel;
      VerticalFormImpl verticalForm = new VerticalFormImpl();
      verticalForm.setName(containerModel.getName());
      List<Form> subforms = verticalForm.getForms();
      for (FormModel subformModel : containerModel.getSubElements()) {
        subforms.add(this.convert(subformModel));
      }
      verticalForm.setForms(subforms);
      form = verticalForm;
    }
    else if (FormType.TAB.equals(formType)) {
      ContainerFormModel containerModel = (ContainerFormModel) formModel;
      TabFormImpl tabForm = new TabFormImpl();
      tabForm.setName(containerModel.getName());
      List<LabeledForm> subforms = tabForm.getForms();
      for (FormModel subformModel : containerModel.getSubElements()) {
        subforms.add((LabeledForm) this.convert(subformModel));
      }
      tabForm.setForms(subforms);
      form = tabForm;
    }
    else if (FormType.LABELED.equals(formType)) {
      ContainerFormModel containerModel = (ContainerFormModel) formModel;
      LabeledFormImpl labeledForm = new LabeledFormImpl();
      labeledForm.setName(containerModel.getName());
      labeledForm.setLabel(new GwtI18nMessage(containerModel.getLabelKey()));
      Form subform = null;
      for (FormModel subformModel : containerModel.getSubElements()) {
        subform = this.convert(subformModel);
      }
      labeledForm.setSubForm(subform);
      form = labeledForm;
    }
    else {
      ItemDescription itemDescription = this.formEditorApplication.getItemFormDescription(formModel.getDescriptionName());
      form = (Form) this.getInstance(itemDescription.getClassName());
      this.setProperty(form, "enabled", formModel.isEnabled());
      this.setProperty(form, "name", formModel.getName());
      this.setProperty(form, "labelKey", new GwtI18nMessage(formModel.getLabelKey()));
      List<VariableModel> parameters = formModel.getParameters();
      for (VariableModel variableModel : parameters) {
        if (variableModel.isLongValue()) {
          this.setProperty(form, variableModel.getName(), Integer.valueOf(variableModel.getValue()));
        }
        else if (variableModel.isBooleanValue()) {
          this.setProperty(form, variableModel.getName(), Boolean.valueOf(variableModel.getValue()));
        }
        else {
          this.setProperty(form, variableModel.getName(), variableModel.getValue());
        }
      }

      if (formModel.canHaveValidator()) {
        Validator validator = (Validator) this.getInstance(formModel.getValidatorClassName());
        for (VariableModel variableModel : formModel.getValidatorParameters()) {
          if (variableModel.isLongValue()) {
            this.setProperty(validator, variableModel.getName(), Integer.valueOf(variableModel.getValue()));
          }
          else if (variableModel.isBooleanValue()) {
            this.setProperty(validator, variableModel.getName(), Boolean.valueOf(variableModel.getValue()));
          }
          else {
            try {
              Class clazz = getPropertyType(validator, variableModel.getName());
              if (GwtI18nMessage.class.equals(clazz)) {
                this.setProperty(validator, variableModel.getName(), new GwtI18nMessage(variableModel.getValue()));
              }
              else {
                this.setProperty(validator, variableModel.getName(), variableModel.getValue());
              }
            }
            catch (Exception e) {
              e.printStackTrace();
            }
          }
        }
        this.setProperty(form, "validator", validator);
      }

      if (formModel.hasEntries()) {
        if (formModel.getEnumEntry() != null && formModel.getEnumEntry().trim().length() != 0) {
          EnumDescriptableValuedItemEntryListImpl enumeration = new EnumDescriptableValuedItemEntryListImpl();
          enumeration.setEnumClassName(formModel.getEnumEntry());
          this.setProperty(form, "entries", enumeration);
        }
        else {
          SimpleValuedItemEntryListImpl list = new SimpleValuedItemEntryListImpl();
          List<VariableModel> entries = formModel.getEntries();
          List<ValuedItemEntry> listEntries = new ArrayList<ValuedItemEntry>();
          ValuedItemEntryImpl entry = null;
          for (VariableModel variable : entries) {
            entry = new ValuedItemEntryImpl();
            entry.setLabel(new GwtI18nMessage(variable.getName()));
            entry.setValue(variable.getValue());
            listEntries.add(entry);
          }
          list.setValuedItemEntries(listEntries);
          this.setProperty(form, "entries", list);
        }
      }
    }
    return form;
  }



  /**
   * Get a property type from a property and its class.
   * 
   * @param obj
   *          on which property exists
   * @param property
   *          to get type
   * @return the Class of the property
   */
  private Class<?> getPropertyType(Object obj, String property)
  {
    Class<?> clazz = null;
    try {
      clazz = PropertyUtils.getPropertyType(obj, property);
    }
    catch (NoSuchMethodException e) {
      e.printStackTrace();
    }
    catch (InvocationTargetException e) {
      e.printStackTrace();
    }
    catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    return clazz;
  }



  /**
   * Get an instance of a specified class.
   * 
   * @param className
   *          the class name.
   * @return the instance.
   */
  private Object getInstance(String className)
  {
    Object instance = null;
    try {
      instance = Class.forName(className).newInstance();
    }
    catch (InstantiationException e) {
      e.printStackTrace();
    }
    catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    catch (ClassNotFoundException e) {
      e.printStackTrace();
    }
    return instance;
  }



  /**
   * Set the bean value property.
   * 
   * @param object
   *          the bean.
   * @param propertyName
   *          the property name.
   * @param value
   *          the value.
   */
  private void setProperty(Object object, String propertyName, Object value)
  {
    try {
      PropertyUtils.setProperty(object, propertyName, value);
    }
    catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    catch (InvocationTargetException e) {
      e.printStackTrace();
    }
    catch (NoSuchMethodException e) {
      e.printStackTrace();
    }
  }



  /**
   * Get the bean value property.
   * 
   * @param object
   *          the bean.
   * @param propertyName
   *          the property name.
   * @return the value.
   */
  private String getProperty(Object object, String propertyName)
  {
    String value = "";
    try {
      value = PropertyUtils.getProperty(object, propertyName).toString();
    }
    catch (IllegalAccessException e) {
      e.printStackTrace();
    }
    catch (InvocationTargetException e) {
      e.printStackTrace();
    }
    catch (NoSuchMethodException e) {
      e.printStackTrace();
    }
    return value;
  }

}
